use ResourceManager;
use MapLoaders;
use Actions;

package Game;



our $rm = ResourceManager->new();
our $mapManager = $rm->getComponent("MapManager");

our $h = 10;
our $w = 10;
our $loader = PlainFileMapLoader->new({FILENAME=>"map"});
$mapManager->registerMap($loader->load,"MAIN");
$mapManager->select("MAIN");


our $display = $rm->getComponent("DisplayManager");
our $input = $rm->getComponent("InputManager");
our $actionMgr = $rm->getComponent("ActionManager");
our $logMgr = $rm->getComponent("LogManager");
our $opMgr = $rm->getComponent("OperationManager");

$logMgr->log("GAME START ====----");

$display->startscr;

# Game loop
my $go = 1;
my @actions;

my $commandName = undef;
my $command = undef;
my $result = undef;
my $action = undef;

## Creating a player and spawner
## -----------------------------
## =============================
my $em = $rm->getComponent("EntityManager");
{
    my $map = $mapManager->getMap("MAIN");
    my $action = undef;

    my %op_params = ("MAP" => $map,
		     "CATEGORY" => "CREATURE");

    # Place the player
    my $player  = $em->spawnEntity("Warrior", "PLAYER");
    $op_params{"ENTITY"} = $player;
    $op_params{"POS"} = [4, 6];
    $opMgr->runOperations(\%op_params, "PlaceEntity");
    
    # Place the spawner
    my $spawner = $em->spawnEntity("Spawner", "SPAWNER");
    $op_params{"ENTITY"} = $spawner;
    $op_params{"POS"} = [52, 8];
    $opMgr->runOperations(\%op_params, "PlaceEntity");
}


## Commands to Actions mapping
## TODO: MOVE THIS SHIT OUT OF HERE!
## ---------------------------
## ===========================
# Command (as returned from the controllers, only KeybordController for now) => Action definition string
%actionBindings = (
    	'Left' => 'Move|DIRECTION=LEFT|WELL_KNOWN_ENTITY=PLAYER',
    	'Up' => 'Move|DIRECTION=UP|WELL_KNOWN_ENTITY=PLAYER',
    	'Down' => 'Move|DIRECTION=DOWN|WELL_KNOWN_ENTITY=PLAYER',
    	'Right' => 'Move|DIRECTION=RIGHT|WELL_KNOWN_ENTITY=PLAYER',
    	'Build' => 'Build|WELL_KNOWN_ENTITY=PLAYER',
    	'Spawn' => 'SpawnCreature|WELL_KNOWN_ENTITY=PLAYER',
    	'Quit' => 'QuitProgramCommand'
    );




## MAIN LOOP
## ---------
## =========
while($go){
    ## Redraw the screen
    ## -----------------
    
    $display->move(0,0);
    drawMap($mapManager->getMap("MAIN"), $display);
    $display->refresh;


    ## Process commands for next turn
    ## ------------------------------
    if($commandName = $input->waitForKeyCommand()){
	if($commandName){
	    $command = $actionMgr->newAction($actionBindings{$commandName});
	    $actionMgr->push($command);
	} # if a valid command occured
    } # waiting for key

    ## Perform last turn's actions
    ## ---------------------------

    while ($action = $actionMgr->pop){
	$result = $action->perform;
	$logMgr->log((ref $action).": ".$result->status->name." - ".$result->msg);
	$go = 0 if($result->is("QUIT"));
    }
    next unless($go); # Quit if an action signaled the game to stop

    ## Activate all entities
    ## ---------------------
    $logMgr->log(" =========== TICKING ==================== ");
    my @entities = @{$em->entities->all};
    foreach my $e(@entities){
	$logMgr->log(" -- ".ref($e));
	$e->tick;
    }
    $logMgr->log(" =========== DONE TICKING =============== ");

    
} # main loop

$rm->disposeComponents;



## Auxiliary functions
## --------------------------------
## ================================


sub drawMap{
    my ($map, $display) = (shift, shift);

    my $tiles = $map->tiles;

    my $tile;

    for(my $y = 0; $y < scalar(@{$tiles->[$x]}); $y++){
	for(my $x = 0; $x < scalar(@{$tiles}); $x++){
	    my $tile = $tiles->[$x][$y];
	    my $pic = $tile->pic;
	    my @constructions = @{$tile->contents->category("CONSTRUCTION")};
	    my @creatures = @{$tile->contents->category("CREATURE")};
	    
	    if(scalar(@creatures) > 0){
		$pic = pop(@creatures)->pic;
	    }
	    elsif (scalar(@constructions) > 0){
		$pic = pop(@constructions)->pic;
	    }
	    else{
		$pic = $tile->contents->category("FLOOR")->[0]->pic;
	    }
	    
	    $display->print($pic);
	} # for x
	
	$display->print("\n");
	
    } # for y
} # drawMap


